#include "Trayectoria.h"

using namespace TP::Matematica;
using namespace TP::Juego::Motorizacion::Fisica;

Trayectoria::Trayectoria() {
	this->_posicionInicial = NULL;
	this->_posicionActual = NULL;
	this->_velocidadInicial = NULL;
	this->_velocidadActual = NULL;
	this->_aceleracion = NULL;
}

Trayectoria::Trayectoria(Posicion* pPosicion, Vector2D* pVelocidad, Vector2D* pAceleracion) {
	// Incialmente, la posicion actual es la posicion inicial.
	this->_posicionInicial = NULL;
	if (pPosicion) {
		this->_posicionInicial = new Posicion();
		this->_posicionInicial->deElementoXML(pPosicion->aElementoXML());
	}
	this->_posicionActual = pPosicion;
	this->_velocidadInicial = NULL;
	if (pVelocidad) {
		this->_velocidadInicial = new Vector2D();
		this->_velocidadInicial->deElementoXML(pVelocidad->aElementoXML());
	}
	this->_velocidadActual = pVelocidad;
	this->_aceleracion = pAceleracion;
}

Trayectoria::~Trayectoria() { }

Posicion* Trayectoria::getPosicionInicial() {
	return this->_posicionInicial;
}

Posicion* Trayectoria::getPosicion() {
	return this->_posicionActual;
}

Vector2D* Trayectoria::getVelocidad() {
	return this->_velocidadActual;
}

Vector2D* Trayectoria::getAceleracion() {
	return this->_aceleracion;
}

Ticks Trayectoria::desplazar(Ticks pTiempo) {
	// Computo la posición siguiente y la configuro como actual.
	Posicion* posicionPost = new Posicion();
	posicionPost->X(_posicionActual->X() + pTiempo * _velocidadActual->X() +
		0.5 * _aceleracion->X() * pow(pTiempo, 2));
	posicionPost->Y(_posicionActual->Y() + pTiempo * _velocidadActual->Y() +
		0.5 * _aceleracion->Y() * pow(pTiempo, 2));
	delete this->_posicionActual;
	this->_posicionActual = posicionPost;

	// Actualizo la velocidad.
	Vector2D* velocidadPost = new Vector2D();
	velocidadPost->X(_velocidadActual->X() + _aceleracion->X() * pTiempo);
	velocidadPost->Y(_velocidadActual->Y() + _aceleracion->Y() * pTiempo);
	delete this->_velocidadActual;
	this->_velocidadActual = velocidadPost;
	return pTiempo;
}

string Trayectoria::aXML() {
	TiXmlDocument* doc = new TiXmlDocument();
	TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "", "");
	doc->LinkEndChild(decl);

	doc->LinkEndChild(this->aElementoXML());

	TiXmlPrinter printer;
	doc->Accept(&printer);
	return printer.CStr();
}

string Trayectoria::aXML(const string& pPath) {
	TiXmlDocument* doc = new TiXmlDocument(pPath.c_str());
	TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "", "");
	doc->LinkEndChild(decl);

	doc->LinkEndChild(this->aElementoXML());

	TiXmlPrinter printer;
	doc->Accept(&printer);
	return printer.CStr();
}

void Trayectoria::parseXML(const string& pDescriptor) {
	TiXmlDocument doc;
	doc.Parse(pDescriptor.c_str(), 0, TIXML_ENCODING_UTF8);
	this->deElementoXML(doc.FirstChildElement());
}

TiXmlElement* Trayectoria::aElementoXML() {
	TiXmlElement * element = new TiXmlElement("Trayectoria");

	if (NULL == this->_posicionInicial)
		element->LinkEndChild(new TiXmlElement("NULL"));
	else
		element->LinkEndChild(this->_posicionInicial->aElementoXML());

	if (NULL == this->_posicionActual)
		element->LinkEndChild(new TiXmlElement("NULL"));
	else
		element->LinkEndChild(this->_posicionActual->aElementoXML());

	if (NULL == this->_velocidadInicial)
		element->LinkEndChild(new TiXmlElement("NULL"));
	else
		element->LinkEndChild(this->_velocidadInicial->aElementoXML());

	if (NULL == this->_velocidadActual)
		element->LinkEndChild(new TiXmlElement("NULL"));
	else
		element->LinkEndChild(this->_velocidadActual->aElementoXML());

	if (NULL == this->_aceleracion)
		element->LinkEndChild(new TiXmlElement("NULL"));
	else
		element->LinkEndChild(this->_aceleracion->aElementoXML());

	return element;
}

void Trayectoria::deElementoXML(TiXmlElement* pElemento) {
	if (strcmp(pElemento->Value(), "Trayectoria") == 0) {

		this->_posicionInicial = NULL;
		if ("NULL" != pElemento->FirstChildElement()->ValueTStr()) {
			this->_posicionInicial = new Posicion();
			this->_posicionInicial->deElementoXML(
					pElemento->FirstChildElement());
		}
		this->_posicionActual = NULL;
		if ("NULL" != pElemento->FirstChildElement(
				)->NextSiblingElement()->ValueTStr()) {
			this->_posicionActual = new Posicion();
			this->_posicionActual->deElementoXML(
					pElemento->FirstChildElement()->NextSiblingElement());
		}
		this->_velocidadInicial = NULL;
		if ("NULL" != pElemento->FirstChildElement()->NextSiblingElement(
				)->NextSiblingElement()->ValueTStr()) {
			this->_velocidadInicial = new Vector2D();
			this->_velocidadInicial->deElementoXML(pElemento->FirstChildElement(
					)->NextSiblingElement()->NextSiblingElement());
		}
		this->_velocidadActual = NULL;
		if ("NULL" != pElemento->FirstChildElement()->NextSiblingElement(
				)->NextSiblingElement()->NextSiblingElement()->ValueTStr()) {
			this->_velocidadActual = new Vector2D();
			this->_velocidadActual->deElementoXML(pElemento->FirstChildElement(
					)->NextSiblingElement()->NextSiblingElement()->NextSiblingElement());
		}
		this->_aceleracion = NULL;
		if ("NULL" != pElemento->FirstChildElement()->NextSiblingElement(
				)->NextSiblingElement()->NextSiblingElement()->NextSiblingElement()->ValueTStr()) {
			this->_aceleracion = new Vector2D();
			this->_aceleracion->deElementoXML(pElemento->FirstChildElement(
					)->NextSiblingElement()->NextSiblingElement(
					)->NextSiblingElement()->NextSiblingElement());
		}
	}
}